/*	
*	IIC Protocol Simulation for STC89C52
*	Author: Kituro
*	Created: 2021.2.18
*	Last changed: 2021.7.10
*	Program Size :
*/

#include <reg52.h>
#include <intrins.h>
#define uchar unsigned char 
#define uint unsigned int 
	
sbit SCL = P2^0;
sbit SDA = P2^1;
sbit led = P1^0;

void nop4()
{
        _nop_();     //等待一个机器周期
        _nop_();     //等待一个机器周期
        _nop_();     //等待一个机器周期
        _nop_();     //等待一个机器周期
}

void IIC_Start(void)
{
        SCL = 1;
        _nop_();
        SDA = 1;
        nop4();
        SDA = 0;
        nop4();
        SCL = 0;
        _nop_();
        _nop_();
}

void IIC_Stop(void)
{
        SDA = 0;
        _nop_();       
        SCL=0;
        nop4();//>4us后SCL跳变
        SCL = 1;
        nop4();
        SDA = 1;
        _nop_();
        _nop_();
}

void IIC_SendACK(bit ACK_Type)
{
        SDA = ACK_Type;
        SCL = 1;
        SCL = 0;
        SDA = 1;                                                        //Release SDA.
}

bit IIC_RecvACK_Error(void)
{
        bit RecvAckError;

        SDA = 1;                                //Write "1" before read.
        SCL = 1;
        RecvAckError = SDA;                //Read SDA.
        SCL = 0;

        return RecvAckError;
}

void IIC_SendOneByte(unsigned char TxValue)
{
        unsigned char i;

        for(i=0; i<8; i++)
        {
                TxValue <<= 1;                        //Data is transferred with MSB first.
                SDA = CY;        //If MSB is 1, the Carry Flag (CY) will be set to 1 after left logical shift, and vice versa.
                _nop_();
                SCL = 1;
                nop4();
                _nop_();   
                SCL = 0;
        }
}

unsigned char IIC_RecvOneByte(void)
{
        unsigned char RxValue = 0;
        unsigned char i;

        SDA = 1;                                                        //Write "1" before read.
        for(i=0; i<8; i++)
        {
                _nop_();
                SCL = 0;
                nop4();
                SCL = 1;
                _nop_();
                _nop_();
                RxValue <<= 1;

                RxValue |= SDA;
                _nop_();
        }
        SCL = 0;
        _nop_();

        return RxValue;
}